/*!
   \file

   \brief
      Encapsulates the general logical flow of the Avion engine.

   © 2011 Mark W. Gabby II

   This file is part of the Avion engine.

   The Avion engine is free software: you can redistribute it and/or modify it under the terms of
   the GNU General Public License as published by the Free Software Foundation, either version 3 of
   the License, or (at your option) any later version.

   The Avion engine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
   without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
   the GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along with the Avion Engine.
   If not, see <http://www.gnu.org/licenses/>.
*/
#include "Systems/AvionEngine/AvionEngine.hpp"

#include "Util/Timer.hpp"

#include "Systems/Audio/Audio.hpp"
#include "Systems/EntManager/EntManager.hpp"
#include "Systems/ErrorManager/ErrorManager.hpp"
#include "Systems/Graphics/Graphics.hpp"
#include "Systems/Input/Input.hpp"
#include "Systems/Physics/Physics.hpp"
#include "Systems/Resource/Resource.hpp"
#include "Systems/Lua/LuaManager.hpp"
#include "Systems/Platform/glCP.hpp"

void AvionEngine::PreWindowInitialize()
{
   GFX.BindCallbacks();
   IP.BindCallbacks();
}

bool AvionEngine::Initialize()
{
   timer.Reset();

   if ( !CONSTANTS.Initialize() )
   {
      return false;
   }

   // Let's hope the error manager doesn't have an error.
   if ( ERRORS.Initialize() == false )
   {
      return false;
   }

   LUA.Initialize();

   // (TEMP - OS needs to be initialized before we can enumerate pixel formats and create a window,
   // all that stuff actually needs to be moved down the pipe to this call instead)
   //OS.Initialize();

   // Initialize the graphics system--------------------------------------
   if ( GFX.Initialize() == false )                                     //
   {
      Error( "Graphics system failed to initialize." );
      return false;
   }                                                                    //
   // End initialize graphics system--------------------------------------

   CrossPlatformOpenGL::Initialize();

   // Initialize the resource manager-------------------------------------
   if ( RESOURCES.Initialize() == false )                               //
   {
      Error( "Resource manager failed to initialize." );

      return false;
   }                                                                    //
   // End initialize resource manager-------------------------------------

   IP.Initialize();

   ENTITIES.Initialize();

   PHYSICS.Initialize();

   AUDIO.Initialize();

   createAppEntityFunction();

   timer.Reset();
   running = true;

   return true;
}
bool AvionEngine::Update()
{
   double Elapsed = timer.Reset();
   // Cap at 1/10th of a second to prevent large jumps, especially when the game is debugged
   if ( Elapsed > 1.0f / 10.0f )
   {
      Elapsed = 1.0f / 10.0f;
   }

   if ( running )
   {
      IP.Update( Elapsed );

      ENTITIES.Update( Elapsed );

      GFX.Update( Elapsed );

      PHYSICS.Update( Elapsed );

      // Stop running if there are no more entities, because nothing
      // happens without entities.
      const int EnabledEntityCount = ENTITIES.GetEnabledEntityCount();

      if ( EnabledEntityCount == 0 )
      {
         return false;
      }
   }

   return true;
}

void AvionEngine::Exit()
{
   AUDIO.Close();

   PHYSICS.Close();

   IP.Close();

   RESOURCES.Close();

   GFX.Close();

   LUA.Close();

   ERRORS.Close();

   CONSTANTS.Close();

   ENTITIES.Close();

   running = false;
}

